const jwt = require('jsonwebtoken')
const Users = require('../models/users')
const crud = require('./crudUtil')

/**
 * 用户登录
 * @param ctx
 * @returns {Promise<void>}
 */
const login = async (ctx) => {
  const {username = '', pwd = ''} = ctx.request.body
  await Users
    .findOne({username, pwd})
    .then(rel => {
      if (rel) {
        const token = jwt.sign({
            username: rel.username,
            _id: rel._id
          },
          'jianshu-server-jwt',
          {expiresIn: 3600 * 24 * 7})
        ctx.body = {
          code: 200,
          msg: '登录成功',
          user: rel,
          token
        }
      } else {
        ctx.body = {
          code: 300,
          msg: '用户名或密码错误'
        }
      }
    })
    .catch(err => {
      ctx.body = {
        code: 500,
        msg: '登录时出现异常'
      }
    })
}

/**
 * 用户注册
 * @param ctx
 * @returns {Promise<void>}
 */
const reg = async (ctx) => {
  const {username = '', pwd = ''} = ctx.request.body
  let isDouble = false
  await Users
    .findOne({username})
    .then(rel => {
      if (rel) {
        isDouble = true
      }
    })
    .catch(err => {
    })
  if (isDouble) {
    ctx.body = {
      code: 300,
      msg: '用户名已经存在'
    }
    return
  }
  await Users
    .create({username, pwd})
    .then(rel => {
      if (rel) {
        ctx.body = {
          code: 200,
          msg: '注册成功'
        }
      } else {
        ctx.body = {
          code: 300,
          msg: '注册失败'
        }
      }
    })
    .catch(err => {
      ctx.body = {
        code: 500,
        msg: '登录时出现异常'
      }
    })
}

/**
 * 验证用户登录
 * @param ctx
 * @returns {Promise<void>}
 */
const verify = async (ctx) => {
  let token = ctx.header.authorization
  token = token.replace('Bearer ', '')
  try {
    const result = jwt.verify(token, 'jianshu-server-jwt')
    await Users
      .findOne({_id: result._id})
      .then(rel => {
        if (rel) {
          ctx.body = {
            code: 200,
            msg: '用户认证成功',
            user: rel
          }
        } else {
          ctx.body = {
            code: 500,
            msg: '用户认证失败'
          }
        }
      })
      .catch(err => {
        ctx.body = {
          code: 500,
          msg: '用户认证失败'
        }
      })
  } catch (err) {
  }
}
/**
 * 修改用户密码
 * @param ctx
 * @returns {Promise<void>}
 */
const updatePwd = async (ctx) => {
  const {username = '', pwd = ''} = ctx.request.body
  await Users
    .updateOne({username}, {pwd})
    .then(rel => {
      if (rel.modifiedCount > 0) {
        ctx.body = {
          code: 200,
          msg: '密码修改成功',
          user: rel
        }
      } else {
        ctx.body = {
          code: 300,
          msg: '密码修改失败'
        }
      }
    })
    .catch(err => {
      ctx.body = {
        code: 500,
        msg: '密码修改失败'
      }
    })
}
/**
 * 修改用户个人资料
 * @param ctx
 * @returns {Promise<void>}
 */
const updatePersonal = async (ctx) => {
  let {_id, avatar = '', sex = '', desc = '', phone = '', email = ''} = ctx.request.body
  await Users
    .updateOne(
      {_id},
      {avatar, sex, desc, phone, email})
    .then(rel => {
      if (rel.modifiedCount > 0) {
        ctx.body = {
          code: 200,
          msg: '资料已更新'
        }
      } else {
        ctx.body = {
          code: 300,
          msg: '资料更新失败'
        }
      }
    })
    .catch(err => {
      ctx.body = {
        code: 500,
        msg: '资料更新失败'
      }
    })
}

const add = async (ctx) => {
  const {username = '', pwd = ''} = ctx.request.body
  await crud.add(Users, {username, pwd}, ctx)
}

const update = async (ctx) => {
  const params = ctx.request.body
  await crud.update(
    Users,
    {_id: params._id},
    {
      username: params.username,
      pwd: params.pwd
    }, ctx)
}

const del = async (ctx) => {
  const {_id} = ctx.request.body
  await crud.del(Users, {_id}, ctx)
}

const find = async (ctx) => {
  await crud.find(Users, null, ctx)
}

const findOne = async (ctx) => {
  await crud.findOne(Users, {_id: ctx.params.id}, ctx)
}

module.exports = {
  login,
  reg,
  verify,
  updatePwd,
  updatePersonal,
  add,
  update,
  del,
  find,
  findOne
}
